package com.tn.tcp;

import cn.hutool.core.util.ArrayUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Slf4j
@Data
@Service
@ChannelHandler.Sharable
public class CardMachineHandle extends ChannelInboundHandlerAdapter {

    @Value("${socket.port:8982}")
    private int cardMachinePort;

    @Resource
    CardMachineInData cardMachineInData;

    // 保存发卡机
    public static final ChannelGroup CMChannels = new DefaultChannelGroup("CardMachineChannelGroup", GlobalEventExecutor.INSTANCE);

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        if(NettyExt.portNotMatched(ctx, cardMachinePort)) {
            ctx.fireChannelActive(); // 不是此连接端口，不处理
            return;
        }

        addChannel(ctx);
//        CMChannels.add(ctx.channel()); // 加到管理组
        log.info("{} > ++++++++++ < {} 连接 成功。 有 {} 个", NettyExt.getServerPort(ctx), NettyExt.getClientIp(ctx), CMChannels.size());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        if(NettyExt.portNotMatched(ctx, cardMachinePort)) {
            ctx.fireChannelInactive(); // 不是此连接端口，不处理
            return;
        }

        log.info("{} x ---------- x {} 连接 断开。 有 {} 个", NettyExt.getServerPort(ctx), NettyExt.getClientIp(ctx), CMChannels.size());
        ctx.close();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if(NettyExt.portNotMatched(ctx, cardMachinePort)) {
            ctx.fireChannelRead(msg); // 不是此连接端口，不处理
            return;
        }
        String msgStr = NettyExt.bufToStr((ByteBuf) msg);
        if(showCMInDataLog) {
            if((!msgStr.startsWith("ACT:heartbeat") && !msgStr.startsWith("ACT:debug") && !msgStr.startsWith("ACT:sync_battery"))|| CardMachineInData.showCMHeartBeatLog) {
                log.info("{} -----> {}", NettyExt.getClientIp(ctx), msgStr);
            }
        }

        cardMachineInData.doCardMachineMessage(ctx, msgStr);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // 异常处理其实也需要判断端口是否匹配。这里暂时不区分
        ctx.close();
//        CMChannels.remove(ctx.channel());
        removeChannel(ctx);
        if(cause.getMessage().startsWith("您的主机中的软件中止了一个已建立的连接")) {
            log.error("{}上 {} 软件中止连接", NettyExt.getServerPort(ctx), NettyExt.getClientIp(ctx));
        } else if(cause.getMessage().startsWith("远程主机强迫关闭了一个现有的连接")) {
            log.error("{}上 {} 远程主机关闭连接：", NettyExt.getServerPort(ctx), NettyExt.getClientIp(ctx));
        } else {
            log.error("{}上 {} 异常: ", NettyExt.getServerPort(ctx), NettyExt.getClientIp(ctx), cause);
        }

    }

    public static int addChannel(ChannelHandlerContext ctx) {
        CardMachineHandle.CMChannels.add(ctx.channel());
        return CardMachineHandle.CMChannels.size();
    }
    public static int removeChannel(ChannelHandlerContext ctx) {
        CardMachineHandle.CMChannels.remove(ctx.channel());
        return CardMachineHandle.CMChannels.size();
    }

    public static boolean showCMInDataLog = true;
}
